// i.r(t), i.d(t, { default: () => SweepPinMesh })
import Module from "./Module"
import * as THREE from "three"
import PinMesh from "../mesh/PinMesh"
import Message from "../message/message"
class PinSelectMessage extends Message {
  sweepId: any
  selected: any
  constructor(e, t) {
    super(), (this.sweepId = e), (this.selected = t)
  }
}
class PinPlacementMessage extends Message {
  sweepId: any
  pinIndex: any
  placed: any
  constructor(e, t, i) {
    super(), (this.sweepId = e), (this.pinIndex = t), (this.placed = i)
  }
}
class SweepPlacedMessage extends Message {
  sweepId: any
  position: any
  constructor(e, t) {
    super(), (this.sweepId = e), (this.position = t)
  }
}
import c from "../math/51263"
import Logger from "../utils/Logger"
import { SweepSelectCommand, SweepHoverCommand } from "../command/sweep.command"
import Comparator from "../utils/Comparator"
import resolutionEnum from "../enum/resolution.enum"
const m = new Logger("pin-mesh")
class PinMeshRenderer {
  sweepViewData: any
  scene: any
  sweepTextureLoader: any
  input: any
  layer: any
  container: THREE.Object3D
  bindings: any[]
  visibilityFilter: (e?: any) => boolean
  updatePlacementType: (e: any, t: any) => void
  dataToMeshMap: any
  engine: any
  onSweepPlacedMessage: (e: any) => void
  hoverSweep: (e: any, t: any) => void
  meshes: any[]
  meshToDataMap: {}
  static MENU_CLEAR_DEBOUNCE: number
  constructor(e, t, i, n, r, o) {
    ;(this.sweepViewData = e),
      (this.scene = t),
      (this.sweepTextureLoader = i),
      (this.input = n),
      (this.layer = o),
      (this.container = new THREE.Object3D()),
      (this.bindings = []),
      (this.visibilityFilter = () => !0),
      (this.updatePlacementType = (e, t) => {
        this.dataToMeshMap[e.id] || e.placementType !== sweepPlacementEnum.MANUAL
          ? this.dataToMeshMap[e.id] &&
            e.placementType !== sweepPlacementEnum.MANUAL &&
            (this.removePinMesh(e), this.engine.broadcast(new PinPlacementMessage(e.id, t, !1)))
          : (this.createPinMesh(e, this.cameraData), this.engine.broadcast(new PinPlacementMessage(e.id, t, !0)))
      }),
      (this.onSweepPlacedMessage = e => {
        this.highlightPin(e.sweepId, !0)
      }),
      (this.hoverSweep = (e, t) => {
        this.issueCommand(new SweepHoverCommand(e, t, 0))
        const i = this.sweepViewData.selectedSweep === e
        this.highlightPin(e, t || i)
      }),
      (this.meshes = []),
      (this.meshToDataMap = {}),
      (this.dataToMeshMap = {}),
      (this.cameraData = r),
      e.iterate(t => {
        t.alignmentType !== sweepAlignmentEnum.ALIGNED &&
          (t.placementType === sweepPlacementEnum.MANUAL && this.createPinMesh(t, r),
          this.bindings.push(
            t.onChanged(() => {
              const i = e.getIndexByAlignment(!1, t.id)
              this.updatePlacementType(t, i), c.H7(t) && this.updatePinMeshPosition(t.id, t.position)
            })
          ))
      })
  }
  cameraData: any
  issueCommand: any
  updatePinMeshPosition(e, t) {
    this.mapSweepToMesh(e).updatePosition(t)
  }
  mapSweepToMesh(e) {
    return this.dataToMeshMap[e]
  }
  mapColliderToSweep(e) {
    const t = e.hasOwnProperty("collider") ? e : e.parent
    if (t) {
      const e = this.meshToDataMap[t.id]
      if (e) return e.sweep
    }
    return null
  }
  filter(e) {
    this.visibilityFilter = e
    for (const e of this.meshes) this.filterMesh(e)
  }
  init() {}
  dispose() {
    for (const e in this.meshToDataMap) {
      const t = this.meshToDataMap[e]
      this.removePinMesh(t.sweep)
    }
  }
  render(e) {
    for (const t of this.meshes) t.render(e)
  }
  activate(e) {
    ;(this.engine = e),
      (this.issueCommand = e.commandBinder.issueCommand.bind(e.commandBinder)),
      this.bindings.push(this.input.registerMeshHandler(HoverEvent, Comparator.isType(PinCollider), (e, t) => this.onHoverEvent(t, !0))),
      this.bindings.push(this.input.registerMeshHandler(UnhoverEvent, Comparator.isType(PinCollider), (e, t) => this.onHoverEvent(t, !1))),
      this.bindings.push(e.subscribe(SweepPlacedMessage, this.onSweepPlacedMessage)),
      this.scene.add(this.container)
  }
  deactivate(e) {
    for (const e of this.bindings) e.cancel()
    ;(this.bindings.length = 0), this.scene.remove(this.container)
  }
  getMeshes() {
    return this.meshToDataMap
  }
  highlightPin(e, t) {
    this.dataToMeshMap[e] && this.dataToMeshMap[e].setPinHover(t ? 1 : 0, !1)
  }
  lockSelection(e, t) {
    return t && (this.engine.broadcast(new PinSelectMessage(e.id, !0)), this.hoverSweep(e.id, !0)), !0
  }
  createPinMesh(e, t) {
    const i = new PinMesh(e.position, null, t, this.layer)
    this.meshes.push(i),
      (this.dataToMeshMap[e.id] = i),
      (this.meshToDataMap[i.id] = { id: i.id, sweep: e }),
      this.container.add(i),
      this.filterMesh(i),
      this.sweepTextureLoader
        .loadFace(e, resolutionEnum.BASE, 1, { flipY: !0 })
        .then(e => {
          i.material.uniforms.tPinHole.value = e
        })
        .catch(t => {
          m.error(`${e.id} failed to load texture: ${t}`)
        })
  }
  removePinMesh(e) {
    const t = this.dataToMeshMap[e.id],
      i = this.meshes.findIndex(e => e.id === t.id)
    this.meshes.splice(i, 1), this.container.remove(t), this.deactivateMesh(t), delete this.meshToDataMap[t.id], delete this.dataToMeshMap[e.id], t.dispose()
  }
  filterMesh(e) {
    const t = this.meshToDataMap[e.id]
    if (t) {
      const i = t.sweep
      this.visibilityFilter(i) ? this.activateMesh(e) : this.deactivateMesh(e)
    }
  }
  onHoverEvent(e, t) {
    const i = this.mapColliderToSweep(e)
    i && this.hoverSweep(i.id, t)
  }
  activateMesh(e) {
    this.input.registerMesh(e.collider, !1), e.activate()
  }
  deactivateMesh(e) {
    this.input.unregisterMesh(e.collider)
    const t = this.meshToDataMap[e.id]
    t && (this.hoverSweep(t.sweep.id, !1), e.deactivate())
  }
}
PinMeshRenderer.MENU_CLEAR_DEBOUNCE = 100
import SweepTextureLoader from "../loader/SweepTextureLoader"
import { PinUnselectCommand } from "../command/pin.command"
class SweepStartedRotatingMessage extends Message {
  sweepId: any
  constructor(e) {
    super(), (this.sweepId = e)
  }
}
class SweepFinishedRotatingMessage extends Message {
  sweepId: any
  constructor(e) {
    super(), (this.sweepId = e)
  }
}
import ModelDataModule from "./ModelDataModule"
import CameraData from "../data/CameraData"
import ViewmodeData from "../data/ViewmodeData"
import SettingsData from "../data/SettingsData"
import FloorsViewData from "../data/FloorsViewData"
import SweepViewData from "../data/SweepViewData"
import toolEnum from "../enum/tool.enum"
import SymbolList from "../SymbolList"
import sweepPlacementEnum from "../enum/sweepPlacement.enum"
import sweepAlignmentEnum from "../enum/sweepAlignment.enum"
import PinCollider from "../mesh/PinCollider"
import keyConst from "../constant/key.const"
import { StartMoveToFloorMessage } from "../message/floor.message"
import { isPanOrMesh } from "../utils/viewmode.util"
import viewmodeEnum from "../enum/viewmode.enum"
import { HoverEvent, UnhoverEvent } from "../event/GestureEvent"
export default class SweepPinMesh extends Module {
  onChange: () => void
  sweepViewData: any
  pinRenderer: any
  settingsData: any
  viewmodeData: any
  nextFloor: any
  onSelectedPinChange: () => void
  engine: any
  model: any
  webglRenderer: any
  input: any
  cameraData: any
  floorsViewData: any
  constructor() {
    super(...arguments),
      (this.name = "sweep-pin-mesh"),
      (this.onChange = () => {
        const e = this.sweepViewData,
          t = e.selectedSweep,
          i = e.toolState === toolEnum.ROTATING || e.toolState === toolEnum.ROTATED
        this.pinRenderer.filter(e => {
          if (!this.settingsData.tryGetProperty(keyConst.rule.features.views, !0)) return !1
          if (i && t === e.id) return !1
          if (this.viewmodeData.transition.active && isPanOrMesh(this.viewmodeData.transition.to)) return !1
          const n = !this.nextFloor || this.nextFloor === e.floorId || !e.floorId,
            s = this.viewmodeData.closestMode === viewmodeEnum.Dollhouse || this.viewmodeData.closestMode === viewmodeEnum.Floorplan
          return n && s
        })
      }),
      (this.onSelectedPinChange = () => {
        const e = this.sweepViewData.selectedSweep
        e && (this.engine.commandBinder.issueCommand(new SweepSelectCommand(e, !0, 0)), this.pinRenderer.highlightPin(e, !0))
      })
  }
  async init(e, t) {
    ;[this.model, this.webglRenderer, this.input, this.sweepViewData, this.cameraData, this.settingsData, this.viewmodeData, this.floorsViewData] =
      await Promise.all([
        t.getModule(ModelDataModule),
        t.getModuleBySymbol(SymbolList.WEBGL_RENDERER),
        t.getModuleBySymbol(SymbolList.INPUT),
        t.market.waitForData(SweepViewData),
        t.market.waitForData(CameraData),
        t.market.waitForData(SettingsData),
        t.market.waitForData(ViewmodeData),
        t.market.waitForData(FloorsViewData)
      ])
    const i = t.claimRenderLayer(this.name),
      n = this.webglRenderer.getScene().scene
    this.engine = t
    const s = new SweepTextureLoader(this.model.getSignedUrls())
    this.pinRenderer = new PinMeshRenderer(this.sweepViewData, n, s, this.input, this.cameraData, i)
    t.addComponent(this, this.pinRenderer)
    this.bindings.push(
      this.settingsData.onPropertyChanged(keyConst.rule.features.views, this.onChange),
      this.viewmodeData.onChanged(this.onChange),
      this.sweepViewData.onSelectedSweepChanged(this.onSelectedPinChange),
      t.subscribe(StartMoveToFloorMessage, e => {
        ;(this.nextFloor = e.to), this.onChange()
      }),
      t.subscribe(SweepStartedRotatingMessage, this.onChange),
      t.subscribe(SweepFinishedRotatingMessage, this.onChange),
      t.commandBinder.addBinding(PinUnselectCommand, async e => {
        this.pinRenderer.highlightPin(e.id, !1)
      })
    )
    this.nextFloor = this.floorsViewData.currentFloorId
    this.onChange()
  }
  mapColliderToSweep(e) {
    return this.pinRenderer.mapColliderToSweep(e)
  }
  selectPinMesh(e, t) {
    return this.pinRenderer.lockSelection(e, t)
  }
  highlightPinMesh(e, t) {
    this.pinRenderer.highlightPin(e, t)
  }
  mapSweepToMesh(e) {
    return this.pinRenderer.mapSweepToMesh(e)
  }
  updatePosition(e, t) {
    this.pinRenderer.updatePinMeshPosition(e, t)
  }
}
